package mail;

import entity.Contact;
import entity.Event;
import entity.Invitation;
import entity.RegisteredUser;
import freemarker.template.Configuration;
import freemarker.template.Template;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import manager.EventManager;
import manager.RegisteredUserManager;
import properties.PropertyHolder;
import utils.HashGenerator;

/**
 *
 * @author dzaric
 */
public class MailClient {

    private static MailClient instance;
    private Properties props;
    private Configuration cfg;

    private MailClient() {
        try {
            cfg = new Configuration();
            URL url = MailClient.class.getResource("templates");
            cfg.setDirectoryForTemplateLoading(new File(url.getFile()));
        } catch (IOException e) {
        }
    }

    public static MailClient getInstance() {
        if (instance == null) {
            instance = new MailClient();
            instance.loadSettings();
        }
        return instance;
    }

    private void loadSettings() {
        this.props = new Properties();

        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.host", PropertyHolder.getProperty("mail.host"));
        props.setProperty("mail.user", PropertyHolder.getProperty("mail.user"));
        props.setProperty("mail.password", PropertyHolder.getProperty("mail.password"));
        props.setProperty("mail.smtp.auth", PropertyHolder.getProperty("mail.smtp.auth"));
        props.setProperty("mail.smtp.port", PropertyHolder.getProperty("mail.smtp.port"));
        props.setProperty("mail.smtp.starttls.enable", PropertyHolder.getProperty("mail.smtp.starttls.enable"));
    }

    private void _sendMail(String recipient, String subject, String messageContent) throws MessagingException {

        //loadSettings();	//uncomment this to load settings each time a message is sent
        Session mailSession = Session.getDefaultInstance(props, new SMTPAuthenticator());
        mailSession.setDebug(true);
        Transport transport = mailSession.getTransport();

        MimeMessage message = new MimeMessage(mailSession);
        message.setSubject(subject);
        message.setContent(messageContent, "text/html; charset=UTF-8");
        message.addRecipient(Message.RecipientType.TO,
                new InternetAddress(recipient));

        transport.connect();
        transport.sendMessage(message,
                message.getRecipients(Message.RecipientType.TO));
        transport.close();
    }

    public static void sendMail(String recipient, String subject, String messageContent) throws MessagingException {
        MailClient.getInstance()._sendMail(recipient, subject, messageContent);
    }

    public static void main(String[] argv) throws Exception {
        RegisteredUserManager rum = new RegisteredUserManager();
        RegisteredUser ru = rum.findAll().get(1);
        EventManager em = new EventManager();
        //Event ev = em.findEventEntities().get(0);

        //sendRegistrationMail(ru);
        //sendEventInvitation(ru.getContacts().get(0), ev);
    }

    private class SMTPAuthenticator extends javax.mail.Authenticator {

        public PasswordAuthentication getPasswordAuthentication() {
            System.out.println(props.getProperty("mail.user"));
            String username = props.getProperty("mail.user");
            String password = props.getProperty("mail.password");
            return new PasswordAuthentication(username, password);
        }
    }

    public static void sendRegistrationMail(RegisteredUser ru) {
        Map params = new HashMap<String, Object>();
        params.put("user", ru);
        params.put("base_url", PropertyHolder.getProperty("BASE_URL"));
        MailClient.sendMailTemplate(ru.getEmail(), "EvIn Registration", "registration", params);
    }

    public static void sendEventInvitation(Invitation invitation) {
        Event event = invitation.getEvent();
        Contact contact = invitation.getContact();
        RegisteredUser ru = event.getRegisteredUser();
        Map params = new HashMap<String, Object>();
        params.put("user", ru);
        params.put("event", event);
        params.put("base_url", PropertyHolder.getProperty("BASE_URL"));
        String verificationCode = HashGenerator.generateHash(contact.getEmail());
        String url = "event/event_display.faces?eventId=" + event.getId() + "&contactId=" + contact.getId() + "&code=" + verificationCode;
        params.put("event_display_url", url);
        MailClient.sendMailTemplate(contact.getEmail(), "Event Invitation", "event_invitation", params);
    }

    public static void sendEventCancelation(Invitation invitation) {
        Event event = invitation.getEvent();
        Contact contact = invitation.getContact();
        RegisteredUser ru = event.getRegisteredUser();
        Map params = new HashMap<String, Object>();
        params.put("user", ru);
        params.put("event", event);
        params.put("base_url", PropertyHolder.getProperty("BASE_URL"));
        MailClient.sendMailTemplate(contact.getEmail(), "Event Cancelation", "event_cancelation", params);
    }

    public static void sendMailTemplate(String recipient, String subject, String templateName, Map<String, Object> params) {
        Template template = getTemplate(templateName);
        StringWriter writer = new StringWriter();
        try {
            template.process(params, writer);
            writer.flush();
            sendMail(recipient, subject, writer.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Template getTemplate(String name) {
        try {
            if (!name.endsWith(".ftl")) {
                name += ".ftl";
            }
            return getInstance().cfg.getTemplate(name);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
